package com.gxar.quick.ar.server.base.facade;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gxar.common.utils.JacksonUtils;
import com.gxar.common.utils.StringUtils;
import com.gxar.quick.ar.server.base.common.enums.WechatTradeStateEnum;
import com.gxar.quick.ar.server.base.common.enums.order.OrderProductTypeEnum;
import com.gxar.quick.ar.server.base.common.enums.order.OrderStatusEnum;
import com.gxar.quick.ar.server.base.common.utils.AesUtils;
import com.gxar.quick.ar.server.base.model.pay.info.WechatPayAmountInfo;
import com.gxar.quick.ar.server.base.model.pay.info.WechatPayResourceInfo;
import com.gxar.quick.ar.server.base.model.pay.info.WechatPrepayAttachInfo;
import com.gxar.quick.ar.server.base.model.pay.vo.request.WechatNotifyRequest;
import com.gxar.quick.ar.server.db.model.TransactionWechatEntity;
import com.gxar.quick.ar.server.db.service.ExchangeItemService;
import com.gxar.quick.ar.server.db.service.OrderService;
import com.gxar.quick.ar.server.db.service.TransactionService;
import com.gxar.quick.ar.server.db.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Map;

/**
 * @author linsy
 * @version 1.0
 * @created 2024/2/21 09:49
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class PayFacade {

    private final TransactionService transactionService;
    private final OrderService orderService;
    private final UserService userService;
    private final ExchangeItemService exchangeItemService;


    /**
     * 回调通知处理
     *
     * @param param 参数
     */
    @Transactional(rollbackFor = Throwable.class)
    public void notify(WechatNotifyRequest param) {
        WechatPayResourceInfo wechatPayResourceInfo = param.getResource();
        try {
            log.info("wechat notify resource: {}", wechatPayResourceInfo);
            String resourceDecrypt = AesUtils.decryptToString(wechatPayResourceInfo.getAssociatedData().getBytes(),
                    wechatPayResourceInfo.getNonce().getBytes(), wechatPayResourceInfo.getCiphertext());
            log.info("resourceDecrypt : {}", resourceDecrypt);
            JSONObject jsonObject = JSON.parseObject(StringUtils.substringBefore(resourceDecrypt, "\n"));
            Long orderId = Long.valueOf(jsonObject.getString("out_trade_no"));
            String attach = jsonObject.getString("attach");
            WechatPrepayAttachInfo attachInfo = JacksonUtils.parseObject(attach, WechatPrepayAttachInfo.class);
            String payer = jsonObject.getString("payer");
            Map<String, String> openIdMap = JacksonUtils.parseMap(payer, String.class, String.class);
            String amount = jsonObject.getString("amount");
            WechatPayAmountInfo wechatPayAmountInfo = JacksonUtils.parseObject(amount, WechatPayAmountInfo.class);
            //保存支付结果
            TransactionWechatEntity transactionWechatEntity = getTransactionWechatEntity(param, attachInfo, jsonObject,
                    attach, openIdMap, wechatPayAmountInfo);
            transactionService.createTransactionWechat(transactionWechatEntity);
            if (WechatTradeStateEnum.SUCCESS.getCode().equals(transactionWechatEntity.getTradeState())) {
                if (OrderProductTypeEnum.EXCHANGE_ITEM.getCode().equals(attachInfo.getType())) {
                    exchangeItemService.exchangeITemPaySuccess(orderId, attachInfo);
                } else {
                    // 会员订单支付成功
                    userService.memberPaySuccess(attachInfo);
                }
                //更新订单状态
                orderService.updateOrderStatusById(orderId, OrderStatusEnum.PAID);
                //更新支付单号
                transactionService.updateTransactionOrderById(attachInfo.getTransactionOrderId(),
                        transactionWechatEntity.getTransactionId(), null);
            } else {
                //更新订单状态
                orderService.updateOrderStatusById(orderId, OrderStatusEnum.CANCELLED);
                //更新失败信息
                transactionService.updateTransactionOrderById(attachInfo.getTransactionOrderId(),
                        transactionWechatEntity.getTransactionId(), transactionWechatEntity.getTradeStateDesc());
            }
        } catch (Exception e) {
            log.error("Notify decryptToString exception : {}", param.getId(), e);
            throw new RuntimeException(e);
        }
    }

    @NotNull
    private static TransactionWechatEntity getTransactionWechatEntity(WechatNotifyRequest param,
                                                                      WechatPrepayAttachInfo attachInfo, JSONObject jsonObject, String attach, Map<String, String> openIdMap,
                                                                      WechatPayAmountInfo wechatPayAmountInfo) {
        TransactionWechatEntity transactionWechatEntity = new TransactionWechatEntity();
        transactionWechatEntity.setId(param.getId());
        transactionWechatEntity.setCreateTime(param.getCreateTime());
        transactionWechatEntity.setEventType(param.getEventType());
        transactionWechatEntity.setResourceType(param.getResourceType());
        transactionWechatEntity.setSummary(param.getSummary());
        transactionWechatEntity.setTransactionOrderId(attachInfo.getTransactionOrderId());
        transactionWechatEntity.setTransactionId(jsonObject.getString("transaction_id"));
        transactionWechatEntity.setTradeType(jsonObject.getString("trade_type"));
        transactionWechatEntity.setTradeState(jsonObject.getString("trade_state"));
        transactionWechatEntity.setTradeStateDesc(jsonObject.getString("trade_state_desc"));
        transactionWechatEntity.setBankType(jsonObject.getString("bank_type"));
        transactionWechatEntity.setAttach(attach);
        transactionWechatEntity.setSuccessTime(jsonObject.getString("success_time"));
        transactionWechatEntity.setOpenId(openIdMap.get("openid"));
        transactionWechatEntity.setTotal(wechatPayAmountInfo.getTotal());
        transactionWechatEntity.setPayerTotal(wechatPayAmountInfo.getPayerTotal());
        transactionWechatEntity.setCurrency(wechatPayAmountInfo.getCurrency());
        transactionWechatEntity.setPayerCurrency(wechatPayAmountInfo.getPayerCurrency());
        return transactionWechatEntity;
    }

}
